import { generateRandomId } from '../utils'
import { isValidMindJson } from '@/utils/validate'
import JSZip from 'jszip'

/**
 * Gmind json 转成 Xmind json
 * @param {*} root
 * @param {*} structureClass xmind结构
 * @returns
 */
export function gmindJsonToXmindJson (root, structureClass) {
  const newRootJson = {}
  const relationships = []
  function walk (rootJson, newNode, isRoot) {
    const { _id, text, comment, link, tag, children, imageInfo, relations } = rootJson
    const newData = {
      id: _id,
      title: text,
      children: {
        attached: [],
        detached: isRoot ? [] : undefined

      },
      structureClass: isRoot ? structureClass : undefined,
      class: isRoot ? 'topic' : undefined
    }
    // 备注
    if (comment) {
      newData.notes = {
        realHTML: {
          content: comment
        },
        plain: {
          content: comment
        }
      }
    }
    // 超链接
    if (link) {
      newData.href = link
    }
    // 标签
    if (tag) {
      newData.labels = tag.split(';')
    }
    // 图片
    if (imageInfo) {
      newData.image = {
        ...imageInfo,
        src: imageInfo.url
      }
    }
    // 关系连线
    if (relations?.length) {
      relations.forEach(o => {
        relationships.push({
          end1Id: o.sourceInfo.id,
          end2Id: o.targetInfo.id,
          id: `${o.relationId}`,
          title: o.relationText
        })
      })
    }

    Object.keys(newData).forEach(key => {
      newNode[key] = newData[key]
    })

    if (children?.length) {
      children.forEach((child, startIdx) => {
        const targetSummarys = child.targetSummarys
        // 概要
        if (targetSummarys?.length) {
          targetSummarys.forEach(o => {
            const endIdx = children.findIndex(k => k._id === o.id)
            newNode.summaries = [...(newNode.summaries || []), {
              id: `${child._id}-${o.id}`,
              range: `(${startIdx},${endIdx})`,
              topicId: `topicId-${child._id}-${o.id}`
            }]
            if (newData.children.summary?.length) {
              newData.children.summary.push({
                id: `topicId-${child._id}-${o.id}`,
                title: o.text
              })
            } else {
              newData.children.summary = [{
                id: `topicId-${child._id}-${o.id}`,
                title: o.text
              }]
            }
          })
        }
        // 外边框
        if (child.outBorder) {
          newNode.boundaries = [...(newNode.boundaries || []), {
            id: `${child._id}-${child._id}`,
            range: `(${startIdx},${startIdx})`,
            title: child.outBorder.text
          }]
        }
        const newChild = {}
        walk(child, newChild)
        // 独立主题
        if (child.pos) {
          newData.children.detached.push({
            ...newChild,
            position: child.pos
          })
        } else {
          newData.children.attached.push(newChild)
        }
      })
    }
  }
  walk(root, newRootJson, true)

  return {
    relationships,
    rootTopic: newRootJson
  }
}

/**
 * Xmind json 转成 Gmind json
 * @param {*} root
 * @param {*} structureClass xmind结构
 * @returns
 */
export async function xmindJsonToGmindJson (xmindJson, zipFiles) {
  const { rootTopic, relationships } = xmindJson
  const newRootJson = {}
  const promiseImageFuncList = []
  async function walk (rootJson, newNode, isRoot = false) {
    const { id, title, boundaries, children, image, href, labels, notes, position } = rootJson
    const { attached = [], detached = [] } = children || {}
    const newData = {
      _id: `mind${id.replace(/-/g, '')}`,
      text: title,
      children: [],
      isRoot,
      childCount: 0,
      expand: true,
      customStyle: null
    }

    if (notes) {
      newData.comment = notes.realHTML?.content
    }

    if (href) {
      newData.link = href
    }

    if (labels?.length) {
      newData.tag = labels.join(';')
    }

    if (position) {
      newData.pos = position
    }

    if (relationships?.length) {
      for (let i = 0; i < relationships.length; i++) {
        const relationItem = relationships[i]
        if (`mind${relationItem.end1Id.replace(/-/g, '')}` === newData._id) {
          newData.relations = [...(newData.relations || []), {
            relationId: generateRandomId(),
            relationText: relationItem.title || '关系',
            sourceInfo: {
              id: newData._id,
              controller: { x: -100, y: 0 },
              point: { x: 0, y: 0 }
            },
            targetInfo: {
              id: `mind${relationItem.end2Id.replace(/-/g, '')}`,
              controller: { x: -100, y: 0 },
              point: { x: 0, y: 0 }
            }
          }]
        }
      }
    }

    Object.keys(newData).forEach(key => {
      newNode[key] = newData[key]
    })

    if (image) {
      promiseImageFuncList.push(async () => {
        newNode.imageInfo = {
          width: image.width,
          height: image.height,
          ...await getImageBase64FromXmind(image.src, zipFiles, image.width && image.height)
        }
      })
    }

    const packageBorder = (boundaries || []).filter(o => {
      const range = o.range.substring(1, o.range.length - 1).split(',')
      return range[0] === range[1]
    }).map(o => {
      const range = o.range.substring(1, o.range.length - 1).split(',')
      return {
        title: o.title,
        idx: Number(range[0])
      }
    })
    if (attached?.length) {
      attached.forEach((child, index) => {
        const newChild = {}
        const t = packageBorder.find(o => o.idx === index)
        if (t) {
          newChild.outBorder = { id: `mind${child.id}`, text: t.title }
        }
        walk(child, newChild)
        newNode.children.push(newChild)
      })
    }
    if (detached?.length) {
      detached.forEach((child) => {
        const newChild = {}
        walk(child, newChild)
        newNode.children.push(newChild)
      })
    }
  }
  walk(rootTopic, newRootJson, true)

  await Promise.all(promiseImageFuncList.map(v => v()))
  return {
    rootTopic: newRootJson,
    skeleton: 'mindMap-defaultSkeleton',
    theme: 'classicsPrimary-0',
    id: xmindJson.id,
    name: xmindJson.title,
    gloabConfig: {}
  }
}

/**
 * .xmind文件解析生成json数据
 * @param {*} file
 */
export function xmindTransformToJson (file) {
  return new Promise((resolve, reject) => {
    JSZip.loadAsync(file).then(async zip => {
      const jsonFile = zip.files['content.json']
      if (jsonFile) {
        const xmindJson = JSON.parse(await jsonFile.async('string'))
        resolve({
          xmindJson,
          zipFiles: zip.files
        })
      } else {
        reject(new Error('该文件无法正常打开，请勿修改并保存，否则文件内容将会永久性丢失！'))
      }
    }).catch(() => {
      reject(new Error('该文件无法正常打开，请勿修改并保存，否则文件内容将会永久性丢失！'))
    })
  })
}

/**
 * 解析上传的.gmind文件和json文件到json数据
 * @param {*} file
 */
export function gmindJsonTransformToJson (file) {
  return new Promise((resolve, reject) => {
    JSZip.loadAsync(file).then(async zip => {
      const jsonFile = zip.files['content.json']
      if (jsonFile) {
        const gmindJson = JSON.parse(await jsonFile.async('string'))
        resolve(gmindJson)
      } else {
        reject(new Error('该文件无法正常打开，请勿修改并保存，否则文件内容将会永久性丢失！'))
      }
    }).catch(() => {
      reject(new Error('该文件无法正常打开，请勿修改并保存，否则文件内容将会永久性丢失！'))
    })
  })
}

/**
 * xmind文件里的图片地址转base64
 * @param {*} src
 * @param {*} zipFiles
 * @param {*} imageSize
 * @returns
 */
export async function getImageBase64FromXmind (src, zipFiles, imageSize) {
  try {
    if (src.includes('xap:resources/') && /\.(jpg|jpeg|png|gif|svg|webp)$/.test(src)) {
      const suffix = /\.([^.]+)$/.exec(src)[1]
      const imageType = suffix === 'svg' ? 'svg+xml' : suffix
      src = `data:image/${imageType};base64,` + (await zipFiles['resources/' + src.split('/')[1]].async('base64'))
    }
    if (!imageSize) {
      const { width, height } = await loadImageAsync(src)
      const max = Math.max(width, height)
      const ratio = max / 180
      return {
        url: src,
        width: width > 180 ? (width / ratio > 180 ? 180 : width / ratio) : width,
        height: height > 180 ? (height / ratio > 180 ? 180 : height / ratio) : height
      }
    }
    return { url: src }
  } catch (error) {
    return null
  }
}

/**
 * 根据图片地址获取图片的尺寸
 * @param {*} url
 * @returns
 */
export function loadImageAsync (url) {
  return new Promise(function (resolve, reject) {
    const image = new Image()
    image.onload = function () {
      resolve(image)
    }
    image.onerror = function () {
      reject(new Error('Could not load image at ' + url))
    }
    image.src = url
  })
}
